#include "Menu.h"

extern volatile uint8_t menuLevel;
extern volatile uint8_t menuControl;
extern volatile uint8_t menuRow;
volatile uint8_t cursorRow;
extern volatile uint8_t setTemp;
volatile uint8_t ctcTemp = 75;			//Get from CTC
volatile uint8_t numMenuStrings[] = {HOME_SIZE, MAIN_MENU_SIZE, INDICATOR_SIZE, ZONE_LIST_SIZE};
char * menuStrings[] = {"Set Temperature ",							//Home (1)
						" Zone Information", " Battery Indicator",	//Main Menu (2)
						" Toggle Indicator",						//Indicator (1)
						" Zone "};									//Zone List (1)
												
extern volatile uint8_t numRTSs;
extern volatile int numSeconds;
extern volatile int turnOffBacklightTime;

volatile uint8_t buttonDown = 0;

void menuInit(void)
{
	menuLevel = HOME;
	menuControl = 0;
	menuRow = 0;
	cursorRow = 0;
	
	//Make Port2, pins 3-6 inputs with internal pull-ups
	//so that buttons to gnd may be connected
	P2DIR &= ~(BIT3 + BIT4 + BIT5 + BIT6);
	P2REN |= (BIT3 + BIT4 + BIT5 + BIT6);
	P2OUT |= (BIT3 + BIT4 + BIT5 + BIT6);
  
  // P2.7 controls the LCD backlight
	P2DIR |= BIT7;
	P2OUT &= ~(BIT7);
	
	//enable high->low edge triggered interrupts for the inputs
	P2IES = (BIT3 + BIT4 + BIT5 + BIT6);
	P2IE = (BIT3 + BIT4 + BIT5 + BIT6);
	P2IFG = 0x00;
	__bis_SR_register(GIE);
}

//Handles the flag returned by the menu button interupt
void menuAction(uint8_t control, RTS_t** RTSarray)
{
<<<<<<< .mine
=======
<<<<<<< .mine
=======
  char i;		//used for the temporary debounce
>>>>>>> .r92
>>>>>>> .r88
  char numMenuItems = 0;
  
  //If displaying info for a zone, ignore all keys but back
  if(menuLevel == ZONE_INFO)
  {
    if(control != MENU_BACK)
    {
      control = 0;
    }
  } 
	
	switch(control)
	{
		case MENU_UP:
			//If at home, raise the temp.  A limit of 90 degrees is in place
			if(menuLevel == HOME)
			{
				if(setTemp < 90)
				{
					setTemp++;
					printMenu(menuLevel, menuRow, RTSarray);
				}
			}
			//or, if inside the menu...
			else
			{
				//check to see if it is possible to scroll up.  menuRow holds the current position
				//that the cursor is at in a given menu level.
				if(menuRow > 0)
				{
					//if it is, move menuRow up one position
					menuRow--;
					//and decide if the cursor should move, or if the whole menu should scroll
					if(cursorRow > 0)
					{
						moveCursor(MENU_UP);
					}
					//if the cursor doesn't need to move, print the new menu screen
					else
					{
						printMenu(menuLevel, menuRow, RTSarray);
					}
				}
			}
			break;
		case MENU_DOWN:
			//If at home, lower the temp.  A limit of 60 degrees is in place
			if(menuLevel == HOME)
			{
				if(setTemp > 60)
				{
					setTemp--;
					printMenu(menuLevel, menuRow, RTSarray);
				}
			}
			//or, if inside the menu...
			else
			{
        if(menuLevel == ZONE_LIST)
        {
          numMenuItems = (numRTSs - 1); //Check variable with CTC, -1 because menuRow starts at 0
        }
        else
        {
          numMenuItems = numMenuStrings[menuLevel] - 1; //-1 because menuRow starts at 0
        }
        
				//check to see if it is possible to scroll down.
				if(menuRow < numMenuItems)
				{
					//if it is, move menuRow down one position
					menuRow++;
					//and decide if the cursor should move, or if the whole menu should scroll
					if(cursorRow < 3)
					{
						moveCursor(MENU_DOWN);
					}
					//if the cursor doesn't need to move, print the new menu screen
					else
					{
						printMenu(menuLevel, (menuRow - 3), RTSarray);
					}
				}
			}
			break;
		case MENU_ENTER:
			switch(menuLevel)
			{
				//If menu level is currently home, move to main menu
				case(HOME):
					menuLevel = MAIN_MENU;
					menuRow = 0;
					break;
				//If menu level is currently main menu, move to either zone info or
				//indicator, based on cursor position.
				case(MAIN_MENU):
					if(menuRow == 0)
					{
						menuLevel = ZONE_LIST;
					}
					else if(menuRow == 1)
					{
						menuLevel = INDICATOR;
					}
					menuRow = 0;
					break;
				case(ZONE_LIST):
          			//make sure there is a zone to print...
          			if(numRTSs > 0) //Check variable with CTC
          			{
            			menuLevel = ZONE_INFO;
					}
					break;
				case(INDICATOR):
					batteryIndicator();
					menuRow = 0;
					break;
			}
			//Return the menuRow to the top, and print the new menu.
			//menuRow = 0;
			moveCursor(HOME);
			printMenu(menuLevel, menuRow, RTSarray);
			break;
		case MENU_BACK:
			switch(menuLevel)
			{
        //If displaying zone info, return to zone list
        case(ZONE_INFO):
          menuLevel = ZONE_LIST;
          break;
				//If the menu is at a level above main menu, go back to main menu
				case(INDICATOR):
				case(ZONE_LIST):
					menuLevel = MAIN_MENU;
					break;
				//or, if at main menu, return home
				case(MAIN_MENU):
					menuLevel = HOME;
					break;
			}
			//Return the menuRow to the top, and print the new menu.
			menuRow = 0;
			moveCursor(HOME);
			printMenu(menuLevel, menuRow, RTSarray);
			break;
	}
	menuControl = 0;
}

void printMenu(uint8_t level, uint8_t row, RTS_t** RTSarray)
{
	char numMenuItems = 0;
	char printMenuStart = 0;
	char i;
	char LCDcursor = 0;
	
	//Begin by clearing the screen, which also returns the cursor to home
	LCDclear();
	
	switch(level)
	{
	  case(ZONE_LIST):
	    numMenuItems = numRTSs;
	    printMenuStart = row;
	    break;
	  case(ZONE_INFO):
	    numMenuItems = 0;
	    break;
	  case(HOME):
	  	numMenuItems = numRTSs + 1;		//+1 is for the set temp;
	  	printMenuStart = 0;				//start at beginning of menuString list
	  default:
	    numMenuItems = numMenuStrings[level];
	    //Find the correct position in menuStrings[] for the given menuLevel.
		//This is done by adding the values in numMenuStrings[]/
	    for(i=0; i<level; i++)
	    {
	    	printMenuStart += numMenuStrings[i];
	    }
	    break;
	} 
  	
	//Now, starting at the current menuRow, print up to four items, depending
	//on how many are in the current menuLevel.
	for(i=row; i<numMenuItems; i++)
	{
		LCDmoveCursor(LCDcursor, 0);
		LCDcursor++;
    
	    if(level == ZONE_LIST)
	    {
			LCDprintString(" Zone ");
			//LCDprintDecimal(5);     //How to access zone ID?  RTSS[i] -> Zone
			LCDprintDecimal(RTSarray[i] -> zone);
	    }
	    else
	    {
	    	LCDprintString(menuStrings[printMenuStart + i]);
	    }
		
		//This checks to see if the bottom of the LCD has been reached.  If so,
		//stop printing.
		if(LCDcursor > 3)
		{
			break;
		}
	}
	
	//If zone info is to be printed...
	if(level == ZONE_INFO)
	{
		LCDprintString("Zone ");
		//LCDprintDecimal(5);     //??RCRs[row] -> zone
		LCDprintDecimal(RTSarray[row] -> zone);
		LCDmoveCursor(1, 0);
		LCDprintString("Temperature: ");
		//LCDprintDecimal(5);     //??RCRs[row] -> temp
		LCDprintDecimal(RTSarray[row] -> temp);
		LCDmoveCursor(2, 0);
		LCDprintString("Battery: ");
		//LCDprintDecimal(5);     //??RCRs[row] -> battery
		LCDprintDecimal(RTSarray[row] -> battLife);
	}
    
	//If the home menu has just been printed, also print the temperatures
	if(level == HOME)
	{
		LCDmoveCursor(0, 16);
		LCDprintDecimal(setTemp);
		for(i=0;i<numRTSs; i++)
		{
			LCDmoveCursor((i+1), 0);
			LCDprintString("Zone ");
			LCDprintDecimal(RTSarray[i] -> zone);
			LCDprintString(" ");
			LCDprintDecimal(RTSarray[i] -> temp);
		}
	}
	//otherwise, print the cursor.
	else
	{
		moveCursor(STAY);
	}
}

void moveCursor(uint8_t direction)
{
	if(menuLevel != ZONE_INFO)
	{
		//start by clearing the current cursor
		LCDmoveCursor(cursorRow, 0);
		LCDwrite(BLANK);
		
		//Based on the desired direction, change cursor row.  If direction
		//is STAY, then don't change cursorRow.
		switch(direction)
		{
			case MENU_DOWN:
				cursorRow++;
				break;
			case MENU_UP:
				cursorRow--;
				break;
			case HOME:
				cursorRow = 0;
				break;
		}
	
		//Draw the new cursor
		LCDmoveCursor(cursorRow, 0);
		LCDwrite(ARROW);
	}
}

void batteryIndicator(void)
{
}

#pragma vector = PORT2_VECTOR
__interrupt void Port2(void)
{
	// disable yourself
	P2IE &= ~(BIT3 + BIT4 + BIT5 + BIT6);
	if(buttonDown == 0)
	{
		buttonDown = 1;
		// flip interrupts to falling edge
		//Make Port2, bits 3-6 outputs for debouncing.  Pins should be made inputs
		//again in main, after appropriate button operation has been performed.
		TA1CCTL1 = CCIE;                        // CCR1 interrupt enabled
		TA1CCR1 = TA1R + DEBOUNCE_TIME;			// Load cap comp register with step period
		P2OUT |= BIT7;							// turn on LCD backlight
		turnOffBacklightTime = numSeconds + 5;
		//Only one button can be read at a time with this switch statement.  If multiple
		//buttons are pressed, nothing will happen.
		//P2IFG &= ~(0x87);
		switch(P2IFG & ~(0x87))
		{
			case MENU_UP:				//Bit 3
				menuControl = MENU_UP;
				break;
			case MENU_DOWN:			//Bit 4
				menuControl = MENU_DOWN;
				break;
			case MENU_ENTER:		//Bit 5
				menuControl = MENU_ENTER;
				break;
			case MENU_BACK:			//Bit 6
				menuControl = MENU_BACK;
				break;
			default:
				break;
				//P2IE |= (BIT3 + BIT4 + BIT5 + BIT6);  //If no valid input, make pins inputs
		}
		P2IES &= ~(BIT3 + BIT4 + BIT5 + BIT6);
	}
	else
	{
		buttonDown = 0;
		// flip to rising edge
		P2IES |= (BIT3 + BIT4 + BIT5 + BIT6);
		TA1CCTL1 = CCIE;                        // CCR1 interrupt enabled
		TA1CCR1 = TA1R + DEBOUNCE_TIME;			// Load cap comp register witdebounce
	}
	// clear the port2 flags
	P2IFG = 0x00;
}

#pragma vector=TIMER1_A1_VECTOR
__interrupt void Timer1_A1 (void)
{
	TA1CCTL1 &= ~(CCIE);					// turn yourself off
	P2IE |= (BIT3 + BIT4 + BIT5 + BIT6);	// reenable button interrupts
	TA1IV &= ~(0x02);
}
